using System;
using System.IO;
using System.Xml;
using System.Xml.Xsl;

using System.Xml.XPath;
namespace Umbraco.Ecommerce.BusinessLogic
{
    public class Store
    {
        private static XmlDocument _XMLDoc = null;
        private static XmlDocument _XslDoc = null;
        private static System.IO.FileSystemWatcher _settingsWatcher;
        private static System.IO.FileSystemWatcher _emailXslWatcher;
        private static string _path = umbraco.GlobalSettings.StorageDirectory;
        private static string _configurationfilename = "ecommerce.conf.xml";
        private static string _emailxslfile = "ecommerce.email.xsl";
        private static string configurationfullpath = _path + "/" + _configurationfilename;
        private static string emailxslfullpath = _path + "/" + _emailxslfile;

        public Store()
        {
        }

        public static string ConfigurationFilePath
        {
            get
            {

                return System.Web.HttpContext.Current.Server.MapPath(configurationfullpath);
            }
        }

        public static string EmailXslFilePath
        {
            get
            {
                return System.Web.HttpContext.Current.Server.MapPath(emailxslfullpath);
            }
        }

        public static string ConfigurationFolderPath
        {
            get
            {
                return System.Web.HttpContext.Current.Server.MapPath(_path);
            }
        }


        private static void ensure()
        {
            if (_XMLDoc == null)
            {
                if (!File.Exists(ConfigurationFilePath))
                {
                    ConfigurationXmlContent = @"<settings>
  <lcid>1030</lcid>
  <deliverycost>45</deliverycost>
  <vatincluded>True</vatincluded>
  <vat>25</vat>
</settings>";
                }

                _XMLDoc = new XmlDocument();
                _XMLDoc.Load(ConfigurationFilePath);

                if (_settingsWatcher == null)
                {
                    _settingsWatcher = new System.IO.FileSystemWatcher(ConfigurationFolderPath, _configurationfilename);
                    _settingsWatcher.NotifyFilter = System.IO.NotifyFilters.LastWrite;
                    _settingsWatcher.Changed += new System.IO.FileSystemEventHandler(_settingsWatcher_Changed);
                    _settingsWatcher.EnableRaisingEvents = true;

                }
            }

            if (_XslDoc == null)
            {

                if (!File.Exists(EmailXslFilePath))
                {
                    EmailXslContent = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n		<!DOCTYPE xsl:Stylesheet [ <!ENTITY nbsp \"&#x00A0;\"> ]>\n<xsl:stylesheet 	version=\"1.0\" \n	xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" \n	xmlns:msxml=\"urn:schemas-microsoft-com:xslt\"\n	xmlns:store.Library=\"urn:store.Library\"\n	exclude-result-prefixes=\"msxml store.Library\">\n   <xsl:output method=\"xml\" omit-xml-declaration=\"yes\"/>\n <xsl:template match=\"/\">\n</xsl:template>\n</xsl:stylesheet>";
                }

                _XslDoc = new XmlDocument();
                _XslDoc.Load(EmailXslFilePath);

                if (_emailXslWatcher == null)
                {
                    _emailXslWatcher = new System.IO.FileSystemWatcher(ConfigurationFolderPath, _emailxslfile);
                    _emailXslWatcher.NotifyFilter = System.IO.NotifyFilters.LastWrite;
                    _emailXslWatcher.Changed += new System.IO.FileSystemEventHandler(_settingsWatcher_Changed);
                    _emailXslWatcher.EnableRaisingEvents = true;
                }
            }
        }

        private static void _settingsWatcher_Changed(object sender, System.IO.FileSystemEventArgs e)
        {
            _XMLDoc = null;
        }

        private static void _emailXslWatcher_Changed(object sender, System.IO.FileSystemEventArgs e)
        {
            _XslDoc = null;
        }

        public static int LCID
        {
            get
            {
                ensure();
                return int.Parse(_XMLDoc.SelectSingleNode("/settings/lcid").InnerText);
            }
        }


        public static bool VatIncludedInPrice
        {
            get
            {
                ensure();
                return bool.Parse(_XMLDoc.SelectSingleNode("/settings/vatincluded").InnerText);
            }
        }

        public static string GetInnerTextByXpath(string XPath)
        {
            try
            {
                return _XMLDoc.SelectSingleNode(XPath).InnerText;
            }
            catch { }
            return "";
        }


        public static int vat
        {
            get
            {
                ensure();
                return int.Parse(_XMLDoc.SelectSingleNode("/settings/vat").InnerText);
            }
        }
        public static string LevID(String country)
        {


            ensure();
            return (_XMLDoc.SelectSingleNode
                ("/settings/DeliveryOrderline/orderline[@country = '" + country + "']/productId").ChildNodes.Item(0).InnerText);

        }
        public static string LevName(String country)
        {
            ensure();
            return (_XMLDoc.SelectSingleNode
                ("/settings/DeliveryOrderline/orderline[@country = '" + country + "']/productName").ChildNodes.Item(0).InnerText);

        }
        public static string GetDeliveryCountry
        {
            get
            {
                ensure();
                return (_XMLDoc.SelectSingleNode
           ("/settings/DeliveryOrderline/orderline/country").InnerText);
            }
        }
        public static decimal GetDeliveryCostByCountry(String country)
        {
            ensure();

            return decimal.Parse(_XMLDoc.SelectSingleNode
            ("/settings/DeliveryOrderline/orderline[@country = '" + country + "']/price").ChildNodes.Item(0).Value);

        }


        public static OrderLine GetDeliveryCost(Decimal OrderTotal)
        {
            ensure();
            XmlNodeList nl = _XMLDoc.SelectNodes("//shipmentOrderline [@type='byPrice']/orderline");
            //XmlNode olNode = null;
            foreach (XmlNode n in nl)
            {
                // Get upper limit
                decimal upperlimit = decimal.Parse(n.Attributes["upperlimit"].Value, InputNumberFormatInfo);
                if (upperlimit >= OrderTotal)
                {
                    return OrderLine.FromXml(n);

                }
            }
            return null;
        }

        public static OrderLine GetDeliveryCostByWeight(Decimal OrderTotal)
        {
            ensure();
            XmlNodeList nl = _XMLDoc.SelectNodes("//shipmentOrderline [@type='byWeight']/orderline");
            //XmlNode olNode = null;
            foreach (XmlNode n in nl)
            {
                // Get upper limit
                decimal upperlimit = decimal.Parse(n.Attributes["upperlimit"].Value, InputNumberFormatInfo);
                if (upperlimit >= OrderTotal)
                {
                    return OrderLine.FromXml(n);

                }
            }
            return null;
        }

        public static System.Globalization.NumberFormatInfo InputNumberFormatInfo
        {
            get
            {
                ensure();
                return new System.Globalization.CultureInfo(1033).NumberFormat;
            }
        }

        public static System.Globalization.NumberFormatInfo NumberFormatInfo
        {
            get
            {
                ensure();
                return new System.Globalization.CultureInfo(LCID).NumberFormat;
            }
        }

        // for xsl
        public static XPathNodeIterator QuerySettingsFile(string XPath)
        {
            ensure();
            return (_XMLDoc.CreateNavigator().Select(XPath));
        }

        // for getting extra values stored in the settingsfile - just apply instant water ;)
        public static string QuerySettingsFileOutput(string XPath)
        {
            ensure();
            XmlNodeList nl = _XMLDoc.SelectNodes(XPath);
            string retval = "";
            foreach (XmlNode child in nl)
            {
                retval += child.InnerXml;
            }
            return retval;
        }


        public static OrderLine PaymentMethodOrderLine(Interfaces.IPaymentMethod pm)
        {
            ensure();
            try
            {
                return OrderLine.FromXml(_XMLDoc.SelectSingleNode("/settings/paymentmethodOrderline/orderline [@paymentmethod='" + pm.Id.ToString().ToLower() + "']"));
            }
            catch
            {

            }
            return null;
        }

        public static string ConfigurationXmlContent
        {
            get
            {
                ensure();
                string retval = "";
                StreamReader sr;
                sr = File.OpenText(ConfigurationFilePath);
                retval = sr.ReadToEnd();
                sr.Close();
                return retval;
            }
            set
            {
                System.IO.StreamWriter sw;
                sw = System.IO.File.CreateText(ConfigurationFilePath);
                sw.Write(value);
                sw.Close();
            }
        }

        public static string EmailXslContent
        {
            get
            {
                ensure();
                string retval = "";
                StreamReader sr;
                sr = File.OpenText(EmailXslFilePath);
                retval = sr.ReadToEnd();
                sr.Close();
                return retval;
            }
            set
            {
                System.IO.StreamWriter sw;
                sw = System.IO.File.CreateText(EmailXslFilePath);
                sw.Write(value);
                sw.Close();
            }
        }

        public static string GetEmailBody(int orderId)
        {
            // System.Globalization.NumberFormatInfo = InputNumberFormatInfo;
            ensure();
            //Load the stylesheet.
            XslTransform xslt = new XslTransform();
            xslt.Load(EmailXslFilePath);
            StringWriter sw = new StringWriter();

            XsltArgumentList xslArgs = new XsltArgumentList();

            Library lib = new Library();
            xslArgs.AddExtensionObject("urn:store.Library", lib);

            umbraco.library lib1 = new umbraco.library();
            xslArgs.AddExtensionObject("urn:umbraco.library", lib1);

            //Create an XmlTextWriter
            XmlTextWriter writer = new XmlTextWriter(sw);

            //Transform the file and send the output to the console.
            xslt.Transform(new Order(orderId).ToXml(), xslArgs, writer, null);

            writer.Close();
            // return the output of the transformation
            string retval = sw.ToString();
            sw.Close();
            return retval;
        }

        public static string GetEmailBody(int orderId, string EmailFilePath)
        {
            // System.Globalization.NumberFormatInfo = InputNumberFormatInfo;
            ensure();
            //Load the stylesheet.
            XslTransform xslt = new XslTransform();
            xslt.Load(EmailFilePath);
            StringWriter sw = new StringWriter();

            XsltArgumentList xslArgs = new XsltArgumentList();

            Library lib = new Library();
            xslArgs.AddExtensionObject("urn:store.Library", lib);

            umbraco.library lib1 = new umbraco.library();
            xslArgs.AddExtensionObject("urn:umbraco.library", lib1);

            //Create an XmlTextWriter
            XmlTextWriter writer = new XmlTextWriter(sw);

            //Transform the file and send the output to the console.
            xslt.Transform(new Order(orderId).ToXml(), xslArgs, writer, null);

            writer.Close();
            // return the output of the transformation
            string retval = sw.ToString();
            sw.Close();
            return retval;
        }
    }
}
